﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar.Controls;
using System.Collections;
using Kugar.Core.ExtMethod;

namespace Kugar.ERPFramework.View.WinForm
{
    public class DetailGridFieldsManager : FieldsManager
    {
        private DataGridView _targetGrid;

        public DetailGridFieldsManager(string detailName, DataGridView targetGrid)
        {
            DetailName = detailName;

            _targetGrid = targetGrid;

            TabIndexList = new List<DetailColumnFieldConfig>();

            _targetGrid.CellValueChanged += _targetGrid_CellValueChanged;

            _targetGrid.CellEndEdit += _targetGrid_CellEndEdit;

            _targetGrid.CellValidating += _targetGrid_CellValidating;

            _targetGrid.EditingControlShowing += _targetGrid_EditingControlShowing;
        }

        public void AddColumn(DetailColumnFieldConfig config)
        {
            base.OnAddField(config);

            TabIndexList.Add(config);
        }

        void _targetGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            var fieldID = _targetGrid.CurrentCell.GetCellColName();

            ((DetailColumnFieldConfig)base[fieldID]).OnEditShowing(e.Control);
        }

        void _targetGrid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            var fieldConfig = this[_targetGrid.Columns[e.ColumnIndex].Name];

            var oldValue=_targetGrid.GetCellValue(e.RowIndex, e.ColumnIndex);

            e.Cancel=!((DetailColumnFieldConfig)fieldConfig).RaiseValueChanging(oldValue, e.FormattedValue);
        }

        void _targetGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            var fieldConfig = this[_targetGrid.Columns[e.ColumnIndex].Name];

            ((DetailColumnFieldConfig)fieldConfig).RaiseValueChanged();
        }

        void _targetGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            //var fieldConfig = this[_targetGrid.Columns[e.ColumnIndex].Name];

            //((DetailColumnFieldConfig) fieldConfig).RaiseValueChanged();

        }

        public object DataSource
        {
            get { return _targetGrid.DataSource; }
            set 
            {
                _targetGrid.DataSource = value;
            }
        }

        public List<DetailColumnFieldConfig> TabIndexList { private set; get; }

        public DetailRow CurrentRow
        {
            set
            {
                value.GridRow.Selected = true;
                _targetGrid.FirstDisplayedScrollingRowIndex = value.GridRow.Index;
            }
            get
            {
                return new DetailRow(this, _targetGrid.CurrentRow);
            }
        }

        public DetailRow GetRow(int index)
        {
            if (index>=_targetGrid.RowCount)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            return new DetailRow(this,_targetGrid.Rows[index]);
        }

        public DetailRow GetFirstDisplayRow()
        {
            return new DetailRow(this,_targetGrid.Rows[_targetGrid.FirstDisplayedScrollingColumnIndex]);
        }

        public FieldConfig GetFirstDisplayColumn()
        {
            var fieldID = _targetGrid.FirstDisplayedCell.GetCellColName();

            return this[fieldID];
        }

        public string DetailName { protected set; get; }

        public void GotoNext()
        {
            if (_targetGrid.Rows.Count <= 0)
            {
                return;
            }



            var currentRow = _targetGrid.CurrentRow ?? _targetGrid.Rows[0];
            var nextFieldID = "";

            if (this.TabIndexList.Count <= 0)
            {
                nextFieldID = _targetGrid.Columns[_targetGrid.CurrentCell.ColumnIndex + 1].Name;
            }
            else
            {
                var nextIndex = (TabIndexList.IndexOf(x => x.FieldName == _targetGrid.CurrentCell.GetCellColName()) + 1)%
                                TabIndexList.Count;

                nextFieldID = TabIndexList[nextIndex].ID;
            }

            if ( _targetGrid.CurrentCell.ColumnIndex == _targetGrid.ColumnCount)
            {
                _targetGrid.CurrentCell = _targetGrid.Rows[currentRow.Index + 1].Cells[nextFieldID];

            }
            else
            {
                _targetGrid.CurrentCell = _targetGrid.Rows[currentRow.Index].Cells[nextFieldID];
            }

            
        }

        

        public void GotoColumn(string fieldID)
        {
            if (_targetGrid.Rows.Count<=0)
            {
                return;
            }

            if (_targetGrid.CurrentRow==null)
            {
                _targetGrid.CurrentCell = _targetGrid.Rows[0].Cells[fieldID];
            }
            else
            {
                 _targetGrid.CurrentCell = _targetGrid.CurrentRow.Cells[fieldID];
            }
           
        }
    }

    public class DetailRow
    {
        private DataGridViewRow _row;
        private FieldsManager _manager;

        internal DetailRow(DetailGridFieldsManager manager, DataGridViewRow row)
        {
            _row = row;

            //_obj = row.DataBoundItem;

            _manager = manager;
        }

        public FieldsManager Manager { get { return _manager; } }

        [Obsolete("不建议直接调用该属性")]
        [Browsable(false)]
        internal DataGridViewRow GridRow { get { return _row; } }

        public bool Visible
        {
            get { return _row.Visible; }
            set { _row.Visible = value; }
        }

        public void SetCellReadOnly(string fieldID, bool readOnly)
        {
            _row.Cells[fieldID].ReadOnly = readOnly;

        }

        public void SetData(string fieldID, object value)
        {
            var oldValue = GetData(fieldID);

            if (oldValue.SafeEquals(value))
            {
                return;
            }
            
            _row.Cells[fieldID].Value = value;

            SetBindingObjData(_manager[fieldID].FieldName, value);
        }

        public Color RowBackColor
        {
            get { return _row.GetCellBackColor(0); }
            set
            {
                _row.SetBackColor(value);
            }
        }

        public void SetRowForeColor(Color color)
        {
            _row.SetRowForeColor(color);
        }

        public void SetCellForeColor(string fieldID, Color color)
        {
            _row.SetCellForeColor(fieldID,color);
        }

        public object GetData(string fieldID)
        {
            return _row.Cells[fieldID].Value;
        }

        public object GetBindingObjData(string fieldID)
        {
            var fieldName = _manager[fieldID].FieldName;

            return _row.DataBoundItem.FastGetValue(fieldName);
        }

        public void SetBindingObjData(string fieldID, object value)
        {
            var fieldName = _manager[fieldID].FieldName;

            var oldValue = GetBindingObjData(fieldName);

            if (oldValue.SafeEquals(value))
            {
                return;
            }

            _row.DataBoundItem.FastSetValue(fieldName,value);

        }

        public object BindingData
        {
            get { return _row.DataBoundItem; }
        }
    }

    public abstract class DetailColumnFieldConfig : FieldConfig
    {
        private DetailGridFieldsManager _manager;

        public DetailColumnFieldConfig()
            : base(null)
        {
            DataFetcher = new DataFetcherManager(this);

            DataFetcher.DataFetherEnabledChanged+=DataFetcher_DataFetherEnabledChanged;
        }



        [Obsolete("不建议直接调用该属性")]
        [Browsable(false)]
        public DataGridViewColumn Column { get; protected set; }

        public DataFetcherManager DataFetcher { get; private set; }

        public event EventHandler ValueChanged;

        internal abstract void ApplyToColumn();   

        public override object Value
        {
            get { return _manager.CurrentRow.GetData(ID); }
            set { _manager.CurrentRow.SetData(ID,value); }
        }

        protected override void OnValueChanged()
        {
            if (ValueChanged!=null)
            {
                ValueChanged(this, EventArgs.Empty);
            }
        }

        protected override void OnLabelTextChanged()
        {
            if (Column != null)
            {
                Column.HeaderText = LabelText;
            }

            base.OnLabelTextChanged();
        }

        protected override void OnVisibleChanged()
        {
            base.OnVisibleChanged();

            if (this.Column != null)
            {
                this.Column.Visible = this.Visible;
            }
        }

        protected abstract void OnDataFetherEnabledChanged();

        protected virtual void GoToNextColumn()
        {
            
        }

        internal  bool RaiseValueChanging(object newValue, object oldValue)
        {
            return base.OnValueChanging(newValue, oldValue);
        }

        internal void RaiseValueChanged()
        {
            OnValueChanged();
        }

        private  void DataFetcher_DataFetherEnabledChanged(object sender, EventArgs e)
        {
            OnDataFetherEnabledChanged();
        }

        protected virtual void ShowDataFether()
        {
            DataFetcher.Show();
        }

        internal virtual void OnEditShowing(Control editControl)
        {
            editControl.KeyDown += editControl_KeyDown;
        }

        void editControl_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode==Keys.Enter && !e.Control)
            {
                if (DataFetcher.HasDataFether)
                {
                    ShowDataFether();
                }
                else
                {
                    GoToNextColumn();
                }

                e.Handled = true;
            }


        }
    }

    public class Detail_NumberColumnFieldConfig : DetailColumnFieldConfig
    {
        public Detail_NumberColumnFieldConfig()
        {
            DataType = typeof(decimal);
        }

        public int DigitCount { set; get; }
        public decimal DefauleValue { set; get; }
        public decimal MaxValue { set; get; }
        public decimal MinValue { set; get; }


        internal override void ApplyToColumn()
        {
            if (string.IsNullOrWhiteSpace(base.LabelText))
            {
                base.LabelText = FieldName;
            }

            if (DigitCount == 0)
            {
                var tempColumn = new DataGridViewIntegerInputColumn();
                tempColumn.DataPropertyName = FieldName;
                tempColumn.MaxValue = (int)MaxValue;
                tempColumn.MinValue = (int)MinValue;
                tempColumn.HeaderText = this.LabelText;
                
                
                tempColumn.ButtonCustomClick += tempColumn_ButtonCustomClick;
                this.Column = tempColumn;
            }
            else
            {
                var tempColumn = new DataGridViewDoubleInputColumn();

                tempColumn.HeaderText = this.LabelText;
                tempColumn.DataPropertyName = FieldName;
                tempColumn.MaxValue = (double)MaxValue;
                tempColumn.MaxValue = (double)MinValue;
                tempColumn.DisplayFormat = "0." + "0".PadRight(DigitCount);

                tempColumn.ButtonCustomClick += tempColumn_ButtonCustomClick;
                this.Column = tempColumn;
            }
            
        }

        protected override void OnDataFetherEnabledChanged()
        {
            if (Column is DataGridViewIntegerInputColumn)
            {
                ((DataGridViewIntegerInputColumn) Column).ButtonCustom.Visible = DataFetcher.HasDataFether;
            }
            else if (Column is DataGridViewDoubleInputColumn)
            {
                ((DataGridViewDoubleInputColumn)Column).ButtonCustom.Visible = DataFetcher.HasDataFether;
            }
        }

        private void tempColumn_ButtonCustomClick(object sender, EventArgs e)
        {
            ShowDataFether();
        }

        protected override void OnIsNullableChanged()
        {
            if (Column is DataGridViewIntegerInputColumn)
            {
                ((DataGridViewIntegerInputColumn)Column).ButtonClear.Visible = IsNullable;
            }
            else if (Column is DataGridViewDoubleInputColumn)
            {
                ((DataGridViewDoubleInputColumn)Column).ButtonClear.Visible = IsNullable;
            }

            base.OnIsNullableChanged();
        }

        protected override void OnEnabledChanged()
        {
            base.OnEnabledChanged();

            if (this.Column != null)
            {
                if (this.Column is DataGridViewDoubleInputColumn)
                {
                    ((DataGridViewDoubleInputColumn)this.Column).Enabled = this.Enabled;
                }
                else
                {
                    ((DataGridViewIntegerInputColumn)this.Column).Enabled = this.Enabled;
                }
            }

        }

        
    }

    public class Detail_TextColumnFieldConfig : DetailColumnFieldConfig
    {
        public Detail_TextColumnFieldConfig()
        {
            base.DataType = typeof(string);
        }

        public int MaxLength { set; get; }

        internal override void ApplyToColumn()
        {
            var column = new DataGridViewTextBoxDropDownColumn();

            column.MaxInputLength = this.MaxLength;

            //column.ButtonCustom.Visible = !string.IsNullOrWhiteSpace(DataFetcherName);
            column.ButtonClear.Visible = true;
            column.ButtonCustom.Visible = base.DataFetcher.HasDataFether;
            column.ButtonCustomClick += tempColumn_ButtonCustomClick;

            this.Column = column;
        }

        protected override void OnDataFetherEnabledChanged()
        {
            ((DataGridViewTextBoxDropDownColumn)Column).ButtonCustom.Visible = base.DataFetcher.HasDataFether;
        }

        private void tempColumn_ButtonCustomClick(object sender, EventArgs e)
        {
            ShowDataFether();
        }

        protected override void OnEnabledChanged()
        {
            base.OnEnabledChanged();

            ((DataGridViewTextBoxDropDownColumn)Column).Enabled = this.Enabled;
        }
    }

    public class Detail_DateTimeColumnFieldConfig : DetailColumnFieldConfig
    {
        public Detail_DateTimeColumnFieldConfig()
        {
            MaxDate = DateTime.MaxValue;
            MinDate = DateTime.MinValue;
            DisplayFormat = "yyyy-MM-dd";

        }

        public string DisplayFormat { set; get; }
        public DateTime MaxDate { set; get; }
        public DateTime MinDate { set; get; }

        internal override void ApplyToColumn()
        {
            var column = new DataGridViewDateTimeInputColumn();

            if (!string.IsNullOrWhiteSpace(DisplayFormat))
            {
                column.CustomFormat = DisplayFormat;
            }

            column.MaxDate = MaxDate;
            column.MinDate = MinDate;

            column.ButtonClear.Visible = IsNullable;
            //column.ButtonCustom.Visible = !string.IsNullOrWhiteSpace(this.DataFetcherName);
            column.ButtonCustom.Visible = DataFetcher.HasDataFether;
            this.Column = column;
        }

        protected override void OnDataFetherEnabledChanged()
        {
            ((DataGridViewDateTimeInputColumn) Column).ButtonCustom.Visible = DataFetcher.HasDataFether;
        }

        protected override void OnIsNullableChanged()
        {
            base.OnIsNullableChanged();

            ((DataGridViewDateTimeInputColumn) Column).ButtonClear.Visible = IsNullable;
        }

        protected override void OnEnabledChanged()
        {
            base.OnEnabledChanged();

            ((DataGridViewDateTimeInputColumn)Column).Enabled = this.Enabled;
        }
    }
}
